package com.ruoyi.food.util;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.springframework.web.multipart.MultipartFile;

import com.ruoyi.food.object.TAttach;

import net.coobird.thumbnailator.Thumbnails;
import ws.schild.jave.Encoder;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;
import ws.schild.jave.info.AudioInfo;
import ws.schild.jave.info.VideoSize;

/**
 * 文件上传工具
 * 
 * @author mengCC
 *
 */
public class UploadUtil {

	/**
	 * 上传图片并压缩(指定宽度和高度)
	 * 
	 * @param string
	 * @param multipartFiles
	 * @param enterpriseId
	 * @param request
	 * @param filePath--上传保存路径
	 * @param presspath--压缩上传保存路径
	 * @param destWidth--压缩的宽
	 * @param destHeight--压缩的高
	 * @return
	 */
	public static List<TAttach> uploadAndCompress(String string, List<MultipartFile> multipartFiles, long enterpriseId,
			HttpServletRequest request, String filePath, String presspath, int destWidth, int destHeight) {

		fileDir(filePath, presspath);
		OutputStream fos = null;
		List<TAttach> tAttachs = new ArrayList<TAttach>();
		for (MultipartFile multipartFile : multipartFiles) {
			try {

				//文件后缀名
				String exe=AnalysisMultipartFileUtil.getExe(multipartFile);
				//新文件名
				String fileName = AnalysisMultipartFileUtil.getNewFileName(multipartFile);

				// 读取源图
				BufferedImage BI = ImageIO.read(multipartFile.getInputStream());
				double srcWidth = BI.getWidth(); // 源图宽度
				double srcHeight = BI.getHeight(); // 源图高度
				if ((int) srcWidth >= destWidth && (int) srcHeight >= destHeight) {

					fos = new FileOutputStream(filePath + fileName);
					Image image = BI.getScaledInstance(destWidth, destHeight, Image.SCALE_SMOOTH);

					BufferedImage tag = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
					Graphics g = tag.getGraphics();
					g.setColor(Color.RED);
					g.drawImage(image, 0, 0, null); // 绘制处理后的图
					g.dispose();
					ImageIO.write(tag, exe, fos);

					TAttach tAttach = setTAttach(fileName, string, enterpriseId, filePath);
					tAttachs.add(tAttach);

				}

			} catch (Exception e) {

			}
		}

		return tAttachs;
	}

	/**
	 * 上传文件(所有类型，不压缩)
	 * 
	 * @param string
	 * @param multipartFiles
	 * @param enterpriseId
	 * @param request
	 * @param filePath--保存文件路径
	 * @return
	 */
	public static List<TAttach> upload(String string, List<MultipartFile> multipartFiles, long enterpriseId,
			HttpServletRequest request, String filePath) {

		BufferedOutputStream stream = null;
		List<TAttach> tAttachs = new ArrayList<TAttach>();
		for (MultipartFile multipartFile : multipartFiles) {
			try {

				//新文件名
				String fileName = AnalysisMultipartFileUtil.getNewFileName(multipartFile);

				byte[] bytes = multipartFile.getBytes();
				stream = new BufferedOutputStream(new FileOutputStream(new File(filePath + fileName)));
				stream.write(bytes);
				stream.close();
				TAttach tAttach = setTAttach(fileName, string, enterpriseId, filePath);
				tAttachs.add(tAttach);
			} catch (Exception e) {

			}
		}

		return tAttachs;
	}

	/**
	 * 视频上传并压缩
	 * @param string
	 * @param multipartFiles
	 * @param enterpriseId
	 * @param request
	 * @param filePath--文件存放位置
	 * @param presspath--压缩文件存放位置
	 * @return
	 */
	public static List<TAttach> uploadVideo(String string, List<MultipartFile> multipartFiles, long enterpriseId,
			HttpServletRequest request, String filePath, String presspath) {
		
		fileDir(filePath, presspath);
		BufferedOutputStream stream = null;
		List<TAttach> tAttachs = new ArrayList<TAttach>();
		File file=null;
		for (MultipartFile multipartFile : multipartFiles) {
			try {

				//新文件名
				String fileName = AnalysisMultipartFileUtil.getNewFileName(multipartFile);
				file =compressionVideo(multipartFile, fileName);
				byte[] bytes=getBytesFromFile(file);
				stream = new BufferedOutputStream(new FileOutputStream(new File(filePath + fileName)));
				stream.write(bytes);
				stream.close();
				TAttach tAttach = setTAttach(fileName, string, enterpriseId, filePath);
				tAttachs.add(tAttach);
			} catch (Exception e) {

			}finally {
				if(file.length()>0) {
					file.delete();
				}
			}
		}

		return tAttachs;
	}
	/**
	 * 从file文件中获取字节数组
	 * @param cntIdImg
	 * @return
	 */
	public static byte[] getBytesFromFile(File cntIdImg){
		 byte[] idImgBytes=null;
		try {
			FileInputStream is = new FileInputStream(cntIdImg); 
	        long length = cntIdImg.length();
	        idImgBytes = new byte[(int)length]; 
	        is.read(idImgBytes);
	        is.close();
		}catch(Exception e) {
			
		}
        

        return idImgBytes;

}

	/**
	 * 对视频进行压缩
	 * @param multipartFile
	 * @param picName
	 * @return
	 */
	public static File compressionVideo(MultipartFile multipartFile,String picName) {
		File source = null;
		File target =null;
		try {
			InputStream ins = null;
            ins = multipartFile.getInputStream();
            source = new File(multipartFile.getOriginalFilename());
            inputStreamToFile(ins, source);
            ins.close();
            
            String newPath = source.getAbsolutePath().substring(0, source.getAbsolutePath().lastIndexOf(File.separator)).concat(File.separator).concat(picName);
            target = new File(newPath);
            
			MultimediaObject object = new MultimediaObject(source);
			AudioInfo audioInfo = object.getInfo().getAudio();
			// 根据视频大小来判断是否需要进行压缩,
			int maxSize = 5;
			double mb = Math.ceil(source.length() / 1048576);
			int second = (int) object.getInfo().getDuration() / 1000;
			BigDecimal bd = new BigDecimal(String.format("%.4f", mb / second));
			System.out.println("开始压缩视频了--> 视频每秒平均 " + bd + " MB ");
			// 视频 > 5MB, 或者每秒 > 0.5 MB 才做压缩
			boolean temp = mb > maxSize || bd.compareTo(new BigDecimal(0.5)) > 0;
			if(temp){
			long time = System.currentTimeMillis();
			// 视频属性设置
			int maxBitRate = 128000;
			int maxSamplingRate = 44100;
			int bitRate = 800000;
			int maxFrameRate = 20;
			int maxWidth = 1280;

			AudioAttributes audio = new AudioAttributes();
			// 设置音频比特率,单位:b (比特率越高，清晰度/音质越好，当然文件也就越大 128000 = 182kb)
			if (audioInfo.getBitRate() > maxBitRate) {
				audio.setBitRate(new Integer(maxBitRate));
			}

			// 设置重新编码的音频流中使用的声道数（1 =单声道，2 = 双声道（立体声））。如果未设置任何声道值，则编码器将选择默认值 0。
			audio.setChannels(audioInfo.getChannels());
			// 采样率越高声音的还原度越好，文件越大
			// 设置音频采样率，单位：赫兹 hz
			// 设置编码时候的音量值，未设置为0,如果256，则音量值不会改变
			// audio.setVolume(256);
			if (audioInfo.getSamplingRate() > maxSamplingRate) {
				audio.setSamplingRate(maxSamplingRate);
			}

			// TODO 视频编码属性配置
			ws.schild.jave.info.VideoInfo videoInfo = object.getInfo().getVideo();
			VideoAttributes video = new VideoAttributes();
			video.setCodec("h264");
			// 设置音频比特率,单位:b (比特率越高，清晰度/音质越好，当然文件也就越大 800000 = 800kb)
			if (videoInfo.getBitRate() > bitRate) {
				video.setBitRate(bitRate);
			}

			// 视频帧率：15 f / s 帧率越低，效果越差
			// 设置视频帧率（帧率越低，视频会出现断层，越高让人感觉越连续），视频帧率（Frame
			// rate）是用于测量显示帧数的量度。所谓的测量单位为每秒显示帧数(Frames per Second，简：FPS）或“赫兹”（Hz）。
			if (videoInfo.getFrameRate() > maxFrameRate) {
				video.setFrameRate(maxFrameRate);
			}

			// 限制视频宽高
			int width = videoInfo.getSize().getWidth();
			int height = videoInfo.getSize().getHeight();
			if (width > maxWidth) {
				float rat = (float) width / maxWidth;
				video.setSize(new VideoSize(maxWidth, (int) (height / rat)));
			}

			EncodingAttributes attr = new EncodingAttributes();
			// attr.setFormat("mp4");
			attr.setAudioAttributes(audio);
			attr.setVideoAttributes(video);
			// 速度最快的压缩方式， 压缩速度 从快到慢： ultrafast, superfast, veryfast, faster, fast, medium,
			// slow, slower, veryslow and placebo.
			//attr.setPreset(PresetUtil.VERYFAST);
			//attr.setCrf(27);
			// // 设置线程数
			// attr.setEncodingThreads(Runtime.getRuntime().availableProcessors()/2);

			Encoder encoder = new Encoder();
			encoder.encode(new MultimediaObject(source), target, attr);
			System.out.println("压缩总耗时：" + (System.currentTimeMillis() - time) / 1000);
			return target;
			 }
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (target.length() > 0) {
				source.delete();
			}
		}
		return source;
	}
	
	 //获取流文件
    public static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	/**
	 * 根据图片大小比例进行压缩上传
	 * 
	 * @param string
	 * @param multipartFiles
	 * @param enterpriseId
	 * @param request
	 * @param filePath
	 * @param presspath--压缩上传保存路径
	 * @return
	 */
	public static List<TAttach> uploadByThum(String string, List<MultipartFile> multipartFiles, long enterpriseId,
			HttpServletRequest request, String filePath, String presspath) {

		fileDir(filePath, presspath);
		BufferedOutputStream stream = null;
		List<TAttach> tAttachs = new ArrayList<TAttach>();
		for (MultipartFile multipartFile : multipartFiles) {
			try {

				//新文件名
				String fileName = AnalysisMultipartFileUtil.getNewFileName(multipartFile);

				byte[] bytes = multipartFile.getBytes();
				float ra = ratio(multipartFile);
				if (Float.compare(ra, 0) == 0) {
					stream = new BufferedOutputStream(new FileOutputStream(new File(filePath + fileName)));
					stream.write(bytes);
					stream.close();
				} else {
					Thumbnails.of(multipartFile.getInputStream()).scale(1f).outputQuality(ra)
							.toFile(filePath + fileName);
				}
				TAttach tAttach = setTAttach(fileName, string, enterpriseId, filePath);				
				tAttachs.add(tAttach);
			} catch (Exception e) {

			}
		}

		return tAttachs;

	}

	/**
	 * 压缩的质量
	 * 
	 * @param multipartFile
	 * @return
	 */
	public static float ratio(MultipartFile multipartFile) {
		long size = multipartFile.getSize();
		long kb = size / 1024;
		float ra = 0;
		if (kb > 100) {
			if (kb > 1000) {
				ra = 0.1f;
			} else {
				float times = (float) 100 / (float) kb;
				// 格式化小数，不足的补0
				DecimalFormat df = new DecimalFormat("0.00");
				String filesize = df.format(times);
				ra = Float.parseFloat(filesize);
			}

		} 
		return ra;

	}

	/**
	 * 判断文件夹是否存在，不存在则创建
	 * @param filePath
	 * @param presspath
	 */
	public static void fileDir(String filePath, String presspath) {
		File file = new File(filePath);
		File pressfile = new File(presspath);
		if (!file.exists()) {
			file.mkdirs();
		}
		if (!pressfile.exists()) {
			pressfile.mkdirs();
		}
	}
	
	/**
	 * 给附件对象赋值
	 * @param fileName
	 * @param string
	 * @param enterpriseId
	 * @param filePath
	 * @return
	 */
	public static TAttach setTAttach(String fileName,String string,long enterpriseId,String filePath) {
		TAttach tAttach = new TAttach();
		tAttach.setAttName(fileName);
		tAttach.setAttFkName(string);
		tAttach.setAttFkId(enterpriseId);
		tAttach.setAttUrl(filePath+fileName);
		tAttach.setAttWebUrl("/upload/" + fileName);

		/*
		 * String hostName =
		 * Address.getHostName(InetAddress.getByName(request.getServerName())); //String
		 * basePath =
		 * request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()
		 * +path; String basePath = request.getScheme()+"://"+hostName.substring(0,
		 * hostName.length()-1)+":"+"8083"+path;
		 */
		tAttach.setAttDomain("http://newsales.chinaesf.net:8083");
		tAttach.setAttTime(new Timestamp(System.currentTimeMillis()));
		return tAttach;
	}

}
